//
//  ViewController.m
//  Lock
//
//  Created by 杨康 on 2017/12/8.
//  Copyright © 2017年 杨康. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
{
    NSLock *lock;
    NSRecursiveLock *recursiveLock;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    lock=[NSLock new];
    recursiveLock = [NSRecursiveLock new];
}
static int i = 0;
- (void)addNum {
    //1、NSLock
    [lock lock];
    NSLog(@"执行开始 i=%d, 线程：%@", i, [NSThread currentThread]);
    i++;
    [NSThread sleepForTimeInterval:1];  //让线程阻塞一秒
    NSLog(@"执行结束 i=%d, 线程：%@", i, [NSThread currentThread]);
    [lock unlock];
}
//我们尽量将lock和unlock写在一起，如果业务需要导致获得锁和解锁的逻辑很分散（或者无法判断是否在同一线程），可以调用-(BOOL)tryLock方法尝试能否获取该锁，方便我们做不同的逻辑
- (void)addNum2 {
    if ([lock tryLock]) {
        NSLog(@"得到锁");
        NSLog(@"执行开始 i=%d, 线程：%@", i, [NSThread currentThread]);
        i++;
        [NSThread sleepForTimeInterval:1];  //让线程阻塞一秒
        NSLog(@"执行结束 i=%d, 线程：%@", i, [NSThread currentThread]);
        [lock unlock];
    } else {
        NSLog(@"没有得到锁");
    }
}
-(void)Action
{
    
    //2、NSConditionLock
    NSConditionLock *clock=[[NSConditionLock alloc]initWithCondition:0];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [clock lockWhenCondition:0];
        NSLog(@"任务1");
        [NSThread sleepForTimeInterval:1.0];
        [clock unlockWithCondition:2];
    });
    
    
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [clock lockWhenCondition:1];
        NSLog(@"任务2");
        [NSThread sleepForTimeInterval:1];
        [clock unlockWithCondition:3];
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [clock lockWhenCondition:2];
        NSLog(@"任务3");
        [NSThread sleepForTimeInterval:1];
        [clock unlockWithCondition:1];
    });
    
    
    
    
    
    
    
    
}
-(void)Action2
{
    //3、NSRecursiveLock
    //为了解决死锁问题
    [recursiveLock lock];
    [recursiveLock lock];
    NSLog(@"得到锁");
    NSLog(@"执行开始 i=%d, 线程：%@", i, [NSThread currentThread]);
    i++;
    [NSThread sleepForTimeInterval:1];  //让线程阻塞一秒
    NSLog(@"执行结束 i=%d, 线程：%@", i, [NSThread currentThread]);
    [recursiveLock unlock];
    [recursiveLock unlock];
}
-(void)Action3
{
    //4、@synchronized
    //@synchronized(obj)，obj参数一般指定为互斥锁要保护的对象。值得提出的是，如果同一个obj对象做为了不同@synchronized(){}的参数，则这些代码块不能同时执行。
    //如果两线程的self相同 那么就是互斥 有一个线程就需要等待（个人理解的obj）
    @synchronized(self)
    {
        NSLog(@"得到锁");
        NSLog(@"执行开始 i=%d, 线程：%@", i, [NSThread currentThread]);
        i++;
        [NSThread sleepForTimeInterval:1];  //让线程阻塞一秒
        NSLog(@"执行结束 i=%d, 线程：%@", i, [NSThread currentThread]);
    }
}
























@end
